require File.dirname(__FILE__)+"/../test_helper"
require "starframe/eventable"

class TestStarFrameEventable < Test::Unit::TestCase
  class TestEvent
    include StarFrame::Eventable
    
    attr_reader :init_calls, :quit_calls, :update_calls, :render_calls
    
    def initialize
      @init_calls = []
      @quit_calls = []
      @update_calls = []
      @render_calls = []
    end
    
    def init *args; @init_calls << [:init, args]; end
    def quit; @quit_calls << :quit; end
    def update; @update_calls << :update; end
    def render; @render_calls << :render; end
  end
  module TestModule
    def call_init_with_module *args; call_init_without_module *args; @init_calls << [:init_ex, args]; end
    def call_quit_with_module; call_quit_without_module; @quit_calls << :quit_ex; end
    def call_update_with_module; call_update_without_module; @update_calls << :update_ex; end
    def call_render_with_module; call_render_without_module; @render_calls << :render_ex; end
    
    def self.included klass
      klass.instance_eval do
        alias_method_chain :call_init, :module
        alias_method_chain :call_quit, :module
        alias_method_chain :call_update, :module
        alias_method_chain :call_render, :module
      end
    end
  end
  class TestIncludedEvent < TestEvent
    include TestModule
    
    def init *args; @init_calls << [:init_or, args]; end
    def quit; @quit_calls << :quit_or; end
    def update; @update_calls << :update_or; end
    def render; @render_calls << :render_or; end
  end
  
  def test_call
    event = TestEvent.new
    event.call
    assert_equal [:update], event.update_calls
  end
  
  def test_calls
    event = TestEvent.new
    
    event.call_init
    assert_equal [[:init, []]], event.init_calls
    
    event.call_quit
    assert_equal [:quit], event.quit_calls
    
    event.call_update
    assert_equal [:update], event.update_calls
    
    event.call_render
    assert_equal [:render], event.render_calls
  end
  
  def test_alias_method_chain
    event = TestIncludedEvent.new
    
    event.call_init
    assert_equal [[:init_or, []], [:init_ex, []]], event.init_calls
    
    event.call_quit
    assert_equal [:quit_or, :quit_ex], event.quit_calls
    
    event.call_update
    assert_equal [:update_or, :update_ex], event.update_calls
    
    event.call_render
    assert_equal [:render_or, :render_ex], event.render_calls
  end
  
  def test_alias_method_chain_with_options
    event = TestIncludedEvent.new
    
    event.call_init :first, :second
    assert_equal [[:init_or, [:first, :second]], [:init_ex, [:first, :second]]], event.init_calls
  end
end
